home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2000 #4
/
Amiga Plus CD - 2000 - No. 4.iso
/
Tools
/
Emulatoren
/
UAE0.6.4
/
src
/
autoconf.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-05-27
|
7KB
|
351 lines
/*
* UAE - The Un*x Amiga Emulator
*
* AutoConfig devices
*
* (c) 1995 Bernd Schmidt
* (c) 1996 Ed Hanway
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include "config.h"
#include "options.h"
#include "memory.h"
#include "custom.h"
#include "newcpu.h"
#include "disk.h"
#include "xwin.h"
#include "autoconf.h"
static struct {
CPTR libbase;
TrapFunction functions[300]; /* I don't think any library has more than 300 functions */
} libpatches[20];
static int n_libpatches = 0;
ULONG Call68k_retaddr(CPTR address, int saveregs, CPTR retaddr)
{
ULONG retval;
CPTR oldpc = m68k_getpc();
struct regstruct backup_regs;
if (saveregs)
backup_regs = regs;
regs.a[7] -= 4;
put_long (regs.a[7], retaddr);
m68k_setpc(address);
m68k_go(0);
retval = regs.d[0];
if (saveregs)
regs = backup_regs;
m68k_setpc(oldpc);
return retval;
}
ULONG Call68k(CPTR address, int saveregs)
{
return Call68k_retaddr(address, saveregs, 0xF0FFF0);
}
ULONG CallLib(CPTR base, WORD offset)
{
int i;
CPTR olda6 = regs.a[6];
ULONG retval;
for (i = 0; i < n_libpatches; i++) {
if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL)
return (*libpatches[i].functions[-offset/6])();
}
regs.a[6] = base;
retval = Call68k(base + offset, 1);
regs.a[6] = olda6;
return retval;
}
/* @$%&§ compiler bugs */
static volatile int four = 4;
CPTR libemu_InstallFunctionFlags(TrapFunction f, CPTR libbase, int offset,
int flags)
{
int i;
CPTR retval;
CPTR execbase = get_long(four);
ULONG addr = here();
calltrap2(deftrap2(f, flags));
dw(RTS);
regs.a[1] = libbase;
regs.a[0] = offset;
regs.d[0] = addr;
retval = CallLib(execbase, -420);
for (i = 0; i < n_libpatches; i++) {
if (libpatches[i].libbase == libbase)
break;
}
if (i == n_libpatches) {
int j;
libpatches[i].libbase = libbase;
for (j = 0; j < 300; j++)
libpatches[i].functions[j] = NULL;
n_libpatches++;
}
libpatches[i].functions[-offset/6] = f;
return retval;
}
CPTR libemu_InstallFunction(TrapFunction f, CPTR libbase, int offset)
{
return libemu_InstallFunctionFlags(f, libbase, offset, 0);
}
/* Commonly used autoconfig strings */
CPTR EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion;
CPTR EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36;
CPTR EXPANSION_bootcode;
static int current_deviceno = 0;
int get_new_device(char **devname, CPTR *devname_amiga)
{
char buffer[80];
sprintf(buffer,"UAE%d", current_deviceno);
*devname_amiga = ds(*devname = strdup(buffer));
return current_deviceno++;
}
/* ROM tag area memory access */
static UBYTE rtarea[65536];
static ULONG rtarea_lget(CPTR) REGPARAM;
static UWORD rtarea_wget(CPTR) REGPARAM;
static UBYTE rtarea_bget(CPTR) REGPARAM;
static void rtarea_lput(CPTR, ULONG) REGPARAM;
static void rtarea_wput(CPTR, UWORD) REGPARAM;
static void rtarea_bput(CPTR, UBYTE) REGPARAM;
static UBYTE *rtarea_xlate(CPTR) REGPARAM;
addrbank rtarea_bank = {
rtarea_lget, rtarea_wget,
rtarea_lget, rtarea_wget, rtarea_bget,
rtarea_lput, rtarea_wput, rtarea_bput,
rtarea_xlate, default_check
};
UBYTE *rtarea_xlate(CPTR addr)
{
addr &= 0xFFFF;
return rtarea + addr;
}
ULONG rtarea_lget(CPTR addr)
{
addr &= 0xFFFF;
return (ULONG)(rtarea_wget(addr) << 16) + rtarea_wget(addr+2);
}
UWORD rtarea_wget(CPTR addr)
{
addr &= 0xFFFF;
return (rtarea[addr]<<8) + rtarea[addr+1];
}
UBYTE rtarea_bget(CPTR addr)
{
UWORD data;
addr &= 0xFFFF;
return rtarea[addr];
}
void rtarea_lput(CPTR addr, ULONG value) { }
void rtarea_bput(CPTR addr, UBYTE value) { }
/* Don't start at 0 -- can get bogus writes there. */
static ULONG trap_base_addr = 0x00F00180;
/* We'll need a lot of these. */
TrapFunction traps[16384];
char trapmode[16384];
static int max_trap = 0;
int lasttrap;
void do_emultrap(int tr)
{
struct regstruct backup_regs;
ULONG retval;
if ((trapmode[tr] & 1) == 0)
backup_regs = regs;
retval = (*traps[tr])();
if ((trapmode[tr] & 1) == 0)
regs = backup_regs;
if ((trapmode[tr] & 2) == 0)
regs.d[0] = retval;
}
void rtarea_wput(CPTR addr, UWORD value)
{
/* Save all registers */
struct regstruct backup_regs;
ULONG retval = 0;
ULONG func = ((addr - trap_base_addr) & 0xFFFF) >> 1;
if (func == 0) {
lasttrap = get_long(regs.a[7]);
regs.a[7] += 4;
regs.spcflags |= SPCFLAG_EMULTRAP;
return;
}
backup_regs = regs;
if(func < max_trap) {
retval = (*traps[func])();
} else {
fprintf(stderr, "illegal emulator trap\n");
}
regs = backup_regs;
regs.d[0] = retval;
}
/* some quick & dirty code to fill in the rt area and save me a lot of
* scratch paper
*/
static int rt_addr = 0;
static int rt_straddr = 0xFF00 - 2;
ULONG addr(int ptr)
{
return (ULONG)ptr + 0x00F00000;
}
void dw(UWORD data)
{
rtarea[rt_addr++] = data >> 8;
rtarea[rt_addr++] = data;
}
void dl(ULONG data)
{
rtarea[rt_addr++] = data >> 24;
rtarea[rt_addr++] = data >> 16;
rtarea[rt_addr++] = data >> 8;
rtarea[rt_addr++] = data;
}
/* store strings starting at the end of the rt area and working
* backward. store pointer at current address
*/
ULONG ds(char *str)
{
int len = strlen(str) + 1;
rt_straddr -= len;
strcpy(rtarea + rt_straddr, str);
return addr(rt_straddr);
}
void calltrap2(ULONG n)
{
dw(0x4878); /* PEA.L n.w */
dw(n);
/* Call trap #0 is reserved for this */
dw(0x33C0); /* MOVE.W D0,abs32 */
dl(trap_base_addr);
}
void calltrap(ULONG n)
{
#if 1
dw(0x33C0); /* MOVE.W D0,abs32 */
dl(n*2 + trap_base_addr);
#else
calltrap2(n);
#endif
}
void org(ULONG a)
{
rt_addr = a - 0x00F00000;
}
ULONG here(void)
{
return addr(rt_addr);
}
int deftrap(TrapFunction func)
{
int num = max_trap++;
traps[num] = func;
trapmode[num] = 0;
return num;
}
int deftrap2(TrapFunction func, int mode)
{
int num = max_trap++;
traps[num] = func;
trapmode[num] = mode;
return num;
}
void align(int b)
{
rt_addr = (rt_addr + (b-1)) & ~(b-1);
}
static ULONG bootcode(void)
{
regs.a[1] = EXPANSION_doslibname;
regs.d[0] = CallLib (regs.a[6], -96); /* FindResident() */
regs.a[0] = get_long(regs.d[0]+22); /* get dos.library rt_init */
return regs.a[0];
}
void rtarea_init()
{
ULONG a;
char uaever[100];
sprintf(uaever, "uae-%d.%d.%d", (version / 100) % 10, (version / 10) % 10, (version / 1) % 10);
EXPANSION_uaeversion = ds(uaever);
EXPANSION_explibname = ds("expansion.library");
EXPANSION_doslibname = ds("dos.library");
EXPANSION_uaedevname = ds("uae.device");
deftrap(NULL); /* Generic emulator trap */
lasttrap = 0;
align(4);
EXPANSION_bootcode = here();
calltrap2(deftrap2(bootcode, 1));
dw(0x2040); /* move.l d0,a0 */
dw(0x4e90); /* jsr (a0) */
dw(RTS);
a = here();
/* Idle task */
org(0xF0FFF0 - 4);
dw(0x4E72); dw (0x2000); /* STOP 0x2000 */
/* Standard "return from 68k mode" trap */
/*org(0xF0FFF0); */
calltrap2(0);
dw(RTS);
org(a);
}